#!/usr/bin/python
# vi:ts=4

import sys,getopt
import commands
import calendar
import textwrap
import locale
import math
import time
import os
import re

import JoDef
import JoLog

import pdb

def usage():
	print """
	Usage: JoPrint [options]
		-h, --help
	"""

def number_format(fmt,num):
    return locale.format(fmt, num, True)

class tablespec:
	"""Defines a table printing specification
		member vars:
			rows    - hash of per-row, column spec overrides
			cols    - array of column spec objects
			table   - array of rows
	"""
	
	def __init__(self,table,*args,**kwargs):
		self.table = table
		self.cols = [];
		self.rows = dict();
		self.props = dict();
		self.props['colpad'] = None;
		self.props['rowpad'] = None;

		try:
			self.props['colpad'] = kwargs['colpad'];
		except:
			pass
		try:
			self.props['rowpad'] = kwargs['rowpad'];
		except:
			pass

	def __getitem__(self,key):
		return self.props[key]
			
	def __setitem__(self,key,val):
		self.props[key] = val;

	def addcol(self,index,*args, **kwargs):
		col = colspec(index,*args,**kwargs)	
		if kwargs.has_key('row'):
			rowind = kwargs['row']
			if rowind == 'last':
				rowind = len(self.table)-1
			if rowind == 'first':
				rowind = 0
			try:
				self.rows[rowind].append(col);	
			except:
				err = "Adding an invalid column (" + rowind
				err +=") to row override"
				JoLog.setup("jo.print").warning(err) 
		else:
			self.cols.append(col);	

	def addrow(self,index):
		if index == 'last':
			index = len(self.table)-1
		if index == 'first':
			index = 0
		self.rows[index] = []	

	def colpad_width(self):
		w = 0
		for c in self.cols:
			for colpad in (c['colpad'],self['colpad']):
				if colpad:
					if type(colpad) == str:
						w += len(colpad)
						break;
					elif type(colpad) == int:
						w += colpad
						break;
		return w	
	def _adjustcols(self,cols):
		z = []
		totalwidth = 0
		colcount = 0
		maxindex = 0
		for c in self.cols:
			if c['index'] > maxindex: maxindex = c['index']
			if c['width'] == 0:
				z.append(c)	
			else:
				totalwidth += c['width'] 
				colcount += 1
		if len(z) > 0:
			fwidth = (JoDef.JOPREF_SCREENWIDTH - totalwidth-self.colpad_width())/len(z)
			for c in z:
				if totalwidth > JoDef.JOPREF_SCREENWIDTH:
					c['width'] = totalwidth/colcount
					totalwidth += c['width']
					colcount += 1
				else:
					c['width'] = fwidth
		if len(self.rows) > 0:
			widths = [0]*(maxindex+1)
			for col in self.cols:
				widths[col['index']] = col['width']
			for row in self.rows:
				for c in self.rows[row]:
					if not c['width']:
						c['width'] = widths[c['index']]
					

	def adjustcols(self):
		self._adjustcols(self.cols)
	
	def printtable(self):
		self.adjustcols()
		locale.setlocale(locale.LC_NUMERIC, '')
		rv = ""
		for ind in range(0,len(self.table)):
			row = self.table[ind]
			text_ls = []
			maxrows = 0
			colspec = self.cols
			if self.rows.has_key(ind):
				colspec = self.rows[ind]
			for c in colspec:
				try:
					cellrows = c.format(row[c['index']])
				except AttributeError:
					cellrows = c.format(str(row[c['index']]))
				if cellrows > maxrows: maxrows = cellrows
			for i in range(0,maxrows):
				for c in colspec:
					rv += c.printcol(i)
					for colpad in (c['colpad'],self['colpad']):
						if colpad:
							if type(colpad) == str:
								rv += colpad
								break
							elif type(colpad) == int:
								rv += " "*colpad
				rv += "\n"
			if self['rowpad']:
				rv += "\n"*self['rowpad']
		return rv

class colspec:
	"""Defines a printable column.
		member vars:
			index   - index into an array (row) of this column
			type    - type of the data in the column
			format  - format for printing
			width   - width of the column
			justify - left, right, center justification
	"""

	def __init__(self,index,*args,**kwargs):
		self.col = []
		self.props  = dict()
		self.props['index'] = index
		self.props['type']  = "string"
		self.props['format'] = "%s"
		self.props['width'] = 0
		self.props['justify'] = "left"
		self.props['colpad'] = None

		try:
			self.props['type'] = kwargs['type'];
		except:
			pass
		try:
			self.props['format'] = kwargs['format'];
		except:
			pass
		try:
			self.props['width'] = kwargs['width'];
		except:
			pass
		try:
			self.props['justify'] = kwargs['justify'];
		except:
			pass
		try:
			self.props['colpad'] = kwargs['colpad'];
		except:
			pass

	def __getitem__(self,key):
		try:
			return self.props[key]
		except:
			return None
			
	def __setitem__(self,key,val):
		try:
			self.props[key] = val;
		except:
			pass

	def format(self,val):
		str = ''
		if( self.props['type'] == 'int' ):
			try:
				str = number_format(self.props['format'],int(val))		
			except:
				str = self.props['format']
		elif( self.props['type'] == 'float' ):
#			try:
				str = number_format(self.props['format'],float(val))		
#			except:
#				str = self.props['format']
		else:
			try:
				str = self.props['format'] % val
			except:
				str = self.props['format']
		self.col = textwrap.wrap(str,self['width'])
		return len(self.col)

	def printcol(self,row):
		if row < len(self.col):	
			if self['justify'] == 'center':
				return self.col[row].center(self['width'])
			elif self['justify'] == 'left':
				return self.col[row].ljust(self['width'])
			elif self['justify'] == 'right':
				return self.col[row].rjust(self['width'])
		else:
			return " "*self['width']

def main():
	try:
		args1 = "h"
		args2 = ["help"]
		opts, args = getopt.getopt(sys.argv[1:], args1,args2)
	except getopt.GetoptError:
		usage()
		sys.exit(2)
	for o,a in opts:
		if o in ("-h", "--help"):
			usage()
			sys.exit()
	# for in opts

	lorem1="""Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."""
	lorem2="""Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."""
	lorem3="""Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."""

	table = [
			 ["col1","col2","col3","col4"],
			 [lorem1,"row1col2","row1col3","102"],
			 ["row2col1",lorem2,"row2col3","324"],
			 ["row3col1","row3col2","row3col3","5352"],
			 ["row4col1","row4col2",lorem3,"34"],
			 ["0.000000",0.000000,"0.000000","4325342.478989"]
			]

	scrw = JoDef.JOPREF_SCREENWIDTH
	tbl = tablespec(table,colpad=2,rowpad=0)
	tbl.addrow('first')
	tbl.addcol(0,row='first',justify='center',format='col1')
	tbl.addcol(1,row='first',justify='center',format='col2')
	tbl.addcol(2,row='first',justify='left',format='col3')
	tbl.addcol(3,row='first',justify='left',format='col4',colpad='\n')
	tbl.addcol(3,row='first',justify='left',width=scrw,format='-'*scrw)
	tbl.addcol(0,width=16,justify='right',format="%s")
	tbl.addcol(1,justify='center')
	tbl.addcol(2,justify='left')
	tbl.addcol(3,justify='left',type="int")
	tbl.addrow('last')
	tbl.addcol(0,row='last',justify='left',width=scrw,format='-'*scrw,colpad='\n')
	tbl.addcol(0,row='last',justify='left',format='')
	tbl.addcol(1,row='last',justify='left',format='')
	tbl.addcol(2,row='last',justify='right',format='Total')
	tbl.addcol(3,row='last',justify='left',type='float',format='%0.2f')
	print tbl.printtable()
		

		
if __name__ == "__main__":
    main()
